package com.shenjianquan.cryptography.utils;

import com.shenjianquan.cryptography.handel.RSAEncrypt;

import java.security.NoSuchAlgorithmException;
import java.util.Map;

public class EncryptionUtils {

    /**
     * 算法中有几个比较关键的变量
     * 1.密钥流 这个是通过秘钥和明文共同生成的
     * 2.状态向量S，长度为256，需要初始化为S[0]=0,S[1]=1....S[255]=255
     * 3.临时向量T，长度和状态向量S一样都是256，如果秘钥的长度刚还为256则直接赋值给T,如果秘钥长度小于256则轮转的方式赋值给T
     * 4.秘钥Key,长度也是1-256字节，这个秘钥就是对明文解密的密码，如果设置过短，容易被暴力搜索，设置在128长度以上会让暴力搜索变得困难，
     * 所以在今后相当长的时间里抵御暴力搜索秘钥的攻击
     *
     * @param aInput 输入字符串
     * @param aKey   输入秘钥
     * @return
     */
    public static String RC4(String aInput,String aKey)
    {
        int[] S = new int[256];
        byte[] T = new byte[256];
        int j = 0 ;
        if (aKey.length()==256){
            T = aKey.getBytes();
            for (int i=0;i<256;i++){
                S[i]=i;
            }
        }else {
            for (int i= 0;i<256;i++)
            {
                T[i]=(byte)aKey.charAt((i % aKey.length()));
                S[i]=i;
            }
        }

        for (int i=0;i<256;i++)
        {
            j=(j+S[i]+T[i]) % 256;
            int temp = S[i];
            S[i]=S[j];
            S[j]=temp;
        }

        int i=0;
        j=0;
        char[] iInputChar = aInput.toCharArray();
        char[] iOutputChar = new char[iInputChar.length];
        for(short x = 0;x<iInputChar.length;x++)
        {
            i = (i+1) % 256;
            j = (j+S[i]) % 256;
            int temp = S[i];
            S[i]=S[j];
            S[j]=temp;
            int t = (S[i]+S[j] ) % 256;
            int K = S[t];
            char iCY = (char)K;
            iOutputChar[x] =(char)( iInputChar[x] ^ iCY) ;


        }
        return new String(iOutputChar);
    }

    public static String HloveyRC4(String aInput,String aKey)
    {
        int[] iS = new int[256];
        byte[] iK = new byte[256];

        for (int i=0;i<256;i++)
            iS[i]=i;

        int j = 1;

        for (short i= 0;i<256;i++)
        {
            iK[i]=(byte)aKey.charAt((i % aKey.length()));
        }

        j=0;

        for (int i=0;i<255;i++)
        {
            j=(j+iS[i]+iK[i]) % 256;
            int temp = iS[i];
            iS[i]=iS[j];
            iS[j]=temp;
        }


        int i=0;
        j=0;
        char[] iInputChar = aInput.toCharArray();
        char[] iOutputChar = new char[iInputChar.length];
        for(short x = 0;x<iInputChar.length;x++)
        {
            i = (i+1) % 256;
            j = (j+iS[i]) % 256;
            int temp = iS[i];
            iS[i]=iS[j];
            iS[j]=temp;
            int t = (iS[i]+(iS[j] % 256)) % 256;
            int iY = iS[t];
            char iCY = (char)iY;
            iOutputChar[x] =(char)( iInputChar[x] ^ iCY) ;
        }

        return new String(iOutputChar);

    }

    public static void encryption(String MingWen,char[] form,int K1,int K2,int[] cipherNum){
        //第一步：将明文存入数组
        char[] pla=new char[MingWen.length()];
        for (int i = 0; i <MingWen.length() ; i++) {
            pla[i]=MingWen.charAt(i);
        }//已将明文存入字符数组pla中
        //第二步：通过脚标找到明文中每个字符对应的数，参与加密运算
        int[] MingWenNumber=new int[pla.length];
        for (int i = 0; i <pla.length ; i++) {
            for (int j = 0; j <form.length ; j++) {
                if (form[j]==pla[i]) {
                    MingWenNumber[i] = j;
                }
            }
        }
        //通过脚标将明文全部转化为数字
        char[] cipher = new char[MingWen.length()];//cipher密码数组  用来存储密文
        for (int i = 0; i <MingWen.length() ; i++) {
            int a= Math.floorMod((K1*MingWenNumber[i]+K2),36);
            cipherNum[i]=a;
            cipher[i]=form[a];
            //计算密文并存入数组中
        }
        System.out.println("加密结果是：");
        System.out.println(cipher);
    }

    public static void decryption(char[] form,String Mingwen,int K2,int K3,int[] cipherNum){
        char[] JieMI=new char[Mingwen.length()];
        for (int i =0;i<Mingwen.length();i++){
            JieMI[i]=form[Math.floorMod(K3*(cipherNum[i]-K2),36)];
        }
        System.out.println("解密结果是：");
        System.out.println(JieMI);
    }

    public static String RSA(String mingWen) throws Exception {
        Map<Integer, String> genKeyPair = RSAEncrypt.genKeyPair();
        String encrypt = RSAEncrypt.encrypt(mingWen, RSAEncrypt.gongyao);
        return encrypt;
    }

    public static String RSADecryp(String miWen) throws Exception {
        Map<Integer, String> genKeyPair = RSAEncrypt.genKeyPair();
        String decrypt = RSAEncrypt.encrypt(miWen, RSAEncrypt.siyao);
        return decrypt;
    }


}
